package com.tcs.reptile.service.impl;

import java.util.Date;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

import javax.annotation.Resource;

import org.apache.commons.lang.math.NumberUtils;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.tcs.model.email.MailSenderInfo;
import com.tcs.model.rule.RuleBean;
import com.tcs.reptile.accept.Accept;
import com.tcs.reptile.concurrent.StockRunnable;
import com.tcs.reptile.service.IRptileServer;
import com.tcs.reptile.service.RunPoac;
import com.tcs.reptile.service.SeekServer;
import com.tcs.rpc.service.IEmailService;
import com.tcs.server.rule.IRuleService;
import com.tcs.server.stock.IStockService;
import com.tcs.util.constant.SystemConstants;
import com.tcs.util.system.MySystemUtil;

/**
 * 股票服务爬虫
* @Title: SotckServerImpl.java
* @Package com.tcs.reptile.impl
* @author 神经刀
* @date 2018年4月9日
* @version V1.0
 */
public class SotckServerImpl implements IRptileServer , RunPoac {
	
	private final Logger logger = LoggerFactory.getLogger(SotckServerImpl.class);
	
	private Integer maxCpuAndFor = 4 , maxId = 0;
	
	private ExecutorService executorService = Executors.newFixedThreadPool(maxCpuAndFor);
	
	@Resource(name="iStockService")
	private IStockService iStockService;
	
	@Resource(name="iEmailService")
	private IEmailService iEmailService;
	
	@Resource(name="iRuleService")
	private IRuleService iRuleService;
	
	@Resource(name="seekServer")
	private SeekServer seekServer;
	
	@Resource(name="mobileAccept")
	private Accept mobileAccept;
	
	private MailSenderInfo mailInfo;
	
	private DateTime dateTime;
	
	private String url;
	
	private String [] Ccs = null;		// 抄送
	
	private CountDownLatch countDownLatch;
	
	private AtomicInteger atomicInteger = new AtomicInteger(0);
	
	@Override
	public void work() {
		int runFalg = NumberUtils.toInt(MySystemUtil.getProperty(SystemConstants.ReptileConstants.RUNFLAG));
		// 1 单线程  ,  2 并发, 为什么会有单线程,因为避免在对方服务器日志留下明显的痕迹引起重视,所以采用慢慢爬的方式,从原来的注重效率改变为注重安全.
		try {
			if (1 == runFalg) {
				SingleRun();
			} else if (2 == runFalg) {
				concurrentRun();
			}
		} catch (Exception e) {
			logger.error("" , e);
		}
	}
	
	@Override
	public void SingleRun() throws Exception {
		Thread thread = new Thread(new StockRunnable(url,++maxId,iStockService,iEmailService,mailInfo,Ccs,countDownLatch,atomicInteger,mobileAccept),"singleRun");
		thread.start();
	}
	
	@Override
	public void concurrentRun() throws Exception {
		StockRunnable stockRunnable = null;
		boolean falg = true;
		while (falg) {
			countDownLatch = new CountDownLatch(maxCpuAndFor);
			atomicInteger.set(0);
			for (int i = 0;i < maxCpuAndFor; i++) {
				stockRunnable = new StockRunnable(url,++maxId,iStockService,iEmailService,mailInfo,Ccs,countDownLatch,atomicInteger,mobileAccept);
				executorService.execute(stockRunnable);
			}
			try {
				countDownLatch.await();
			} catch (InterruptedException e) {
				logger.error("" , e);
			}
			if (atomicInteger.get() >= 2) {
				falg = false;
			}
		}
		System.exit(1);
	}
	
	@Override
	public void init() {
		try {
			maxId = iStockService.maxId();
			url = iStockService.getUrl();
			dateTime = new DateTime(new Date());
			if (setCcs()) {
				if (!isGoseek()) {
					logger.info(" 今天是节假日或者休息日! ");
				} else {
					// 7点-17点之间工作,其他时间不工作,以免引起服务方的注意
					int hour = dateTime.getHourOfDay();
					logger.info(" 工作日  7点-18点之间工作,其他时间不工作,以免引起服务方的注意 , 当前时间 : {}" , hour);
					if (hour >= 7 && hour <= 18) {
						this.work();
					}
				}
			} else {
				logger.error(" 设置Ccs 抄送邮箱 异常" ,new NullPointerException("数组为空或者发生异常,导致无法进行下一步操作!"));
			}
		} catch (Exception e) {
			logger.error("", e);
		} finally {
			System.exit(0);
		}
	}
	
	/**
	* @Title: isGoseek  
	* @Description: 是否节假日,休息日,工作日
	* @return boolean   2节假日,1休息日,0工作日  <code>true</code> : 2节假日,1休息日  , <code>false</code> : 工作日
	*/
	public boolean isGoseek() {
		return seekServer.isSeek() == 0;
	}
	
	/**
	* @Title: setCcs  
	* @Description: 设置抄送邮箱
	* @return boolean    返回类型  
	 */
	private boolean setCcs() {
		boolean result = false;
		try {
			Ccs = iRuleService.getCcs(new RuleBean(SystemConstants.ProductConstants.STOCK_CRAWLER, 0));
			if (null != Ccs && Ccs.length > 0) {
				result = true;
			}
		} catch (Exception e) {
			logger.error("" , e);
		}
		return result;
	}
}